//
//  AppleScriptManager.m
//  Pennyworth
//
//  Created by Chris Karr on 4/28/08.
//  Copyright 2008 Chris Karr. All rights reserved.
//

#import "AppleScriptManager.h"
#import <Carbon/Carbon.h>

#define SCRIPT_URL @"http://pennyworth.aetherial.net/scripts/scripts.xml"
#define NAME @"name"
#define TYPE @"type"
#define STATUS @"status"
#define VERSION @"version"
#define DESCRIPTION @"description"
#define INSTALL @"installed"
#define PATH @"path"

@implementation AppleScriptManager

- (NSString *) callFunction:(NSString *) function onScript:(NSString *) scriptPath
{
	NSDictionary * errors = [NSDictionary dictionary];
	NSURL * scriptUrl = [NSURL fileURLWithPath:scriptPath];
	
	NSAppleScript * scpt = [[NSAppleScript alloc] initWithContentsOfURL:scriptUrl error:nil];
	
	if (scpt != nil)
	{
		ProcessSerialNumber psn = { 0, kCurrentProcess };
		NSAppleEventDescriptor * target = [NSAppleEventDescriptor descriptorWithDescriptorType:typeProcessSerialNumber
																							 bytes:&psn
																							length:sizeof(ProcessSerialNumber)];
				
		NSAppleEventDescriptor * handler = [NSAppleEventDescriptor descriptorWithString:function];
				
		NSAppleEventDescriptor * event = [NSAppleEventDescriptor appleEventWithEventClass:kASAppleScriptSuite
																				  eventID:kASSubroutineEvent
																		 targetDescriptor:target
																				 returnID:kAutoGenerateReturnID
																			transactionID:kAnyTransactionID];
				
		[event setParamDescriptor:handler forKeyword:keyASSubroutineName];
			
		NSAppleEventDescriptor * results = [scpt executeAppleEvent:event error:&errors];
		
		[scpt release];

		if (results != nil)
			return [results stringValue];
	}
	
	return nil;
}

- (IBAction) refresh:(id) sender
{
	[appleScripts setFilterPredicate:nil];
	[appleScripts removeObjects:[appleScripts arrangedObjects]];
	
	NSFileManager * manager = [NSFileManager defaultManager];
	
	NSArray * directories = NSSearchPathForDirectoriesInDomains (NSApplicationSupportDirectory, NSUserDomainMask, YES);
	
	NSString * folder = [NSString stringWithFormat:@"%@/Pennyworth/AppleScript", [directories lastObject]];
	
	for (NSString * file in [manager directoryContentsAtPath:folder])
	{
		if ([file hasSuffix:@".scpt"])
		{
			NSString * fullPath = [NSString stringWithFormat:@"%@/%@", folder, file];
			
			NSMutableDictionary * action = [NSMutableDictionary dictionary];
		
			[action setValue:[file stringByDeletingPathExtension] forKey:NAME];
			[action setValue:@"Action" forKey:TYPE];
			[action setValue:@"Installed" forKey:STATUS];
			[action setValue:[NSNumber numberWithBool:YES] forKey:INSTALL];
			[action setValue:[self callFunction:@"script_version" onScript:fullPath] forKey:VERSION];
			[action setValue:[self callFunction:@"script_description" onScript:fullPath] forKey:DESCRIPTION];
			[action setValue:fullPath forKey:PATH];
			
			[appleScripts addObject:action];
		}
	}

	folder = [NSString stringWithFormat:@"%@/Pennyworth/AppleScript/Sensors", [directories lastObject]];
	
	for (NSString * file in [manager directoryContentsAtPath:folder])
	{
		if ([file hasSuffix:@".scpt"])
		{
			NSString * fullPath = [NSString stringWithFormat:@"%@/%@", folder, file];
			
			NSMutableDictionary * sensor = [NSMutableDictionary dictionary];
			
			[sensor setValue:[file stringByDeletingPathExtension] forKey:NAME];
			[sensor setValue:@"Sensor" forKey:TYPE];
			[sensor setValue:@"Installed" forKey:STATUS];
			[sensor setValue:[NSNumber numberWithBool:YES] forKey:INSTALL];
			[sensor setValue:[self callFunction:@"script_version" onScript:fullPath] forKey:VERSION];
			[sensor setValue:[self callFunction:@"script_description" onScript:fullPath] forKey:DESCRIPTION];
			[sensor setValue:fullPath forKey:PATH];
			
			[appleScripts addObject:sensor];
		}
	}

	if ([[NSUserDefaults standardUserDefaults] boolForKey:@"Online_AppleScripts"])
	{
		NSURL * url = [NSURL URLWithString:SCRIPT_URL];
		NSURLRequest * request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData 
											  timeoutInterval:10];
		
		NSURLResponse * response;
		NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];

		if (data == nil)
			return;
		
		NSError * error = nil;
		
		NSXMLDocument * scriptXML = [[NSXMLDocument alloc] initWithData:data options:NSXMLNodeOptionsNone error:nil];
									// [[NSXMLDocument alloc] initWithContentsOfURL:[NSURL URLWithString:SCRIPT_URL]
									// 									 options:NSXMLDocumentTidyXML
									//									   error:&error];
		
		if (scriptXML != nil)
		{
			NSXMLElement * root = [scriptXML rootElement];
			
			for (NSXMLElement * scriptElement in [root elementsForName:@"script"])
			{
				NSMutableDictionary * script = [NSMutableDictionary dictionary];
				
				[script setValue:[[scriptElement attributeForName:NAME] stringValue] forKey:NAME];
				[script setValue:[[scriptElement attributeForName:TYPE] stringValue] forKey:TYPE];
				[script setValue:@"Not installed" forKey:STATUS];
				[script setValue:[NSNumber numberWithBool:NO] forKey:INSTALL];
				[script setValue:[[scriptElement attributeForName:VERSION] stringValue] forKey:VERSION];
				[script setValue:[scriptElement stringValue] forKey:DESCRIPTION];
				[script setValue:[[scriptElement attributeForName:@"url"] stringValue] forKey:PATH];
				BOOL install = YES;
				
				for (NSDictionary * entry in [appleScripts arrangedObjects])
				{
					if ([[script valueForKey:@"name"] isEqualToString:[entry valueForKey:@"name"]] &&
						[[script valueForKey:TYPE] isEqualToString:[entry valueForKey:TYPE]] &&
						[[script valueForKey:VERSION] isEqualToString:[entry valueForKey:VERSION]])
						install = NO;
				}
				
				if (install)
					[appleScripts addObject:script];
			}
		}
		else
			NSRunAlertPanel ([error localizedFailureReason], [error localizedDescription], @"OK", nil, nil);
	}

}

- (IBAction) open:(id) sender
{
	NSDictionary * selected = [[appleScripts selectedObjects] lastObject];
	
	if ([[selected valueForKey:STATUS] isEqualToString:@"Installed"])
		[[NSWorkspace sharedWorkspace] openFile:[selected valueForKey:PATH]];
	else
		[self install:sender];
}

- (void) awakeFromNib
{
	[tableView setTarget:self];
	[tableView setDoubleAction:@selector(open:)];
	[self refresh:self];
}

- (IBAction) install:(id) sender
{
	NSDictionary * selected = [[appleScripts selectedObjects] lastObject];

	if (NSOKButton == NSRunInformationalAlertPanel (@"Install Script?", 
													[NSString stringWithFormat:@"Would you like to install the '%@' script?", 
																			   [selected valueForKey:@"name"]], @"Yes", @"No", nil))
	{
		NSArray * directories = NSSearchPathForDirectoriesInDomains (NSApplicationSupportDirectory, NSUserDomainMask, YES);
		NSString * path = [selected valueForKey:PATH];
		
		NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:path]];
		NSMutableString * prefix = [NSMutableString stringWithFormat:@"%@/Pennyworth/AppleScript", [directories lastObject]];
		
		if ([[selected valueForKey:TYPE] isEqualToString:@"Sensor"])
			[prefix appendString:@"/Sensors"];
		
		NSString * file = [path lastPathComponent];
		
		NSString * finalPath = [[NSString stringWithFormat:@"%@/%@", prefix, file] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
		
		NSFileManager * manager = [NSFileManager defaultManager];

		if ([manager fileExistsAtPath:finalPath])
			[manager movePath:finalPath toPath:[finalPath stringByReplacingOccurrencesOfString:@".scpt" 
																					withString:@".scpt-old"]
																					   handler:nil];
		
		[data writeToFile:finalPath atomically:YES];
		[data release];
		
		[self refresh:sender];
	}
}

- (IBAction) invoke:(id) sender
{
	[panel makeKeyAndOrderFront:sender];
}

@end
